package ar.com.algotres.tpdos.modelo.disparos.estrategias;

import java.util.ArrayList;
import java.util.List;

import ar.com.algotres.tpdos.modelo.disparos.Disparo;
import ar.com.algotres.tpdos.modelo.disparos.PosicionAExplotarInvalidaExcpetion;
import ar.com.algotres.tpdos.modelo.fisica.CoordenadasDePosicioInvalidaException;
import ar.com.algotres.tpdos.modelo.fisica.Posicion;
import ar.com.algotres.tpdos.modelo.fisica.direcciones.Direccion;
import ar.com.algotres.tpdos.modelo.fisica.direcciones.DireccionAbajo;
import ar.com.algotres.tpdos.modelo.fisica.direcciones.DireccionArriba;
import ar.com.algotres.tpdos.modelo.fisica.direcciones.DireccionDerecha;
import ar.com.algotres.tpdos.modelo.fisica.direcciones.DireccionDiagonalAbajoDerecha;
import ar.com.algotres.tpdos.modelo.fisica.direcciones.DireccionDiagonalAbajoIzquierda;
import ar.com.algotres.tpdos.modelo.fisica.direcciones.DireccionDiagonalArribaDerecha;
import ar.com.algotres.tpdos.modelo.fisica.direcciones.DireccionDiagonalArribaIzquierda;
import ar.com.algotres.tpdos.modelo.fisica.direcciones.DireccionIzquierda;
import ar.com.algotres.tpdos.modelo.tablero.Tablero;

public class EstrategiaDeImpactoTriple implements EstrategiaDeImpacto {

	private void agregarCasillerosEntreDos(List<Posicion> posiciones,
			Posicion posicion) throws CoordenadasDePosicioInvalidaException {
		Posicion pivote;

		pivote = this.moverAlBorde(new DireccionAbajo(), posicion);
		this.agregarInternoInferiorOSuperior(posiciones, pivote);
		pivote = this.moverAlBorde(new DireccionArriba(), posicion);
		this.agregarInternoInferiorOSuperior(posiciones, pivote);

		pivote = this.moverAlBorde(new DireccionIzquierda(), posicion);
		this.agregarInternoLaterales(posiciones, pivote);
		pivote = this.moverAlBorde(new DireccionDerecha(), posicion);
		this.agregarInternoLaterales(posiciones, pivote);
	}

	private void agregarDosSiguienteEnDireccion(List<Posicion> posiciones,
			Posicion actual, Direccion direccion)
			throws CoordenadasDePosicioInvalidaException {
		Posicion posicionAux;
		posicionAux = actual.siguienteEn(direccion);
		posiciones.add(posicionAux);
		posicionAux = posicionAux.siguienteEn(direccion);
		posiciones.add(posicionAux);
	}

	private void agregarInternoInferiorOSuperior(List<Posicion> posiciones,
			Posicion pivote) throws CoordenadasDePosicioInvalidaException {
		posiciones.add(pivote.siguienteEn(new DireccionDerecha()));
		posiciones.add(pivote.siguienteEn(new DireccionIzquierda()));
	}

	private void agregarInternoLaterales(List<Posicion> posiciones,
			Posicion pivote) throws CoordenadasDePosicioInvalidaException {
		posiciones.add(pivote.siguienteEn(new DireccionAbajo()));
		posiciones.add(pivote.siguienteEn(new DireccionArriba()));
	}

	@Override
	public void impactarEn(Posicion posicion, Disparo propietario) throws PosicionAExplotarInvalidaExcpetion {
		try {
			List<Posicion> posiciones = this.posicionesADisparar(posicion);
			for (Posicion posicionADisparar : posiciones) {
				Tablero.getInstance().explosionEn(posicionADisparar,
						propietario);
			}
		} catch (CoordenadasDePosicioInvalidaException e) {
			// TODO:crear exception
		}
	}

	private Posicion moverAlBorde(Direccion direccion, Posicion posicion)
			throws CoordenadasDePosicioInvalidaException {
		Posicion pivote;
		pivote = posicion.siguienteEn(direccion);
		pivote = pivote.siguienteEn(direccion);
		return pivote;
	}

	private List<Posicion> posicionesADisparar(Posicion posicion)
			throws CoordenadasDePosicioInvalidaException {

		List<Posicion> posiciones = new ArrayList<>();
		posiciones.add(posicion);
		this.agregarDosSiguienteEnDireccion(posiciones, posicion,
				new DireccionAbajo());
		this.agregarDosSiguienteEnDireccion(posiciones, posicion,
				new DireccionArriba());
		this.agregarDosSiguienteEnDireccion(posiciones, posicion,
				new DireccionIzquierda());
		this.agregarDosSiguienteEnDireccion(posiciones, posicion,
				new DireccionDerecha());
		this.agregarDosSiguienteEnDireccion(posiciones, posicion,
				new DireccionDiagonalAbajoDerecha());
		this.agregarDosSiguienteEnDireccion(posiciones, posicion,
				new DireccionDiagonalAbajoIzquierda());
		this.agregarDosSiguienteEnDireccion(posiciones, posicion,
				new DireccionDiagonalArribaDerecha());
		this.agregarDosSiguienteEnDireccion(posiciones, posicion,
				new DireccionDiagonalArribaIzquierda());
		this.agregarCasillerosEntreDos(posiciones, posicion);
		return posiciones;
	}
}
